using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using Jonathan.SharpDB;
using System.Windows.Forms;
using System.Collections;
using System.Threading;
using Jonathan.AlphaGradientPanel;

namespace Jonathan
{
	/// <summary>
	/// Delegate to add an Item to the Reference list.
	/// </summary>
	/// <param name="item"></param>
    public delegate void DelAddRefItem (string item);

	/// <summary>
	/// Delegate to perform actions after the reference list is fully loaded.
	/// </summary>
    public delegate void DelRefLoaded ();

	/// <summary>
	/// A Control that will Display the different Texts Jonathan handles.
	/// </summary>
    public partial class ctrlReader : Tabber.TabberPage, IWebberHost
    {
        private string m_Abbrevation;
        private frmMain m_FormMain;
        private string m_Type;
        private ToolStripMenuItem m_tsmiAdd;
        private List<cJData.icDBInfo> m_Versions;
        private List<cPassage> m_Passages;
        private bool m_TSK;
        private DelAddRefItem m_AddRef;
        private DelRefLoaded m_RefLoaded;
        private bool m_Loaded;

        #region - Constructor -

		/// <summary>
		/// Creates a new Reader Control.
		/// </summary>
		/// <param name="main">Reference to Main Form.</param>
		/// <param name="version">Version of text to load.</param>
		/// <param name="filePath">Path to version.</param>
        public ctrlReader(frmMain main, string version, string filePath):base(version)
        {
            this.m_FormMain = main;
            this.m_Loaded = false;
            this.GetBookType(filePath);
            InitializeComponent(main);

            this._Working.Visible = false;
            this.splitContainer1.Panel2.Resize += new EventHandler(ReaderPanel_Resize);
            this.Load += new EventHandler(ctrlReader_Load);
            this.m_Versions = new List<cJData.icDBInfo>();
            this.m_Versions.Add(new cJData.icDBInfo(filePath, version));
            this.m_Passages = null;
            this.m_AddRef = new DelAddRefItem(this.AddRefWord);
            this.m_RefLoaded = new DelRefLoaded(this.RefLoaded);
            this.TabButton.ButtonToolTip = version;

            Jonathan.ColorPicker.ToolStripColorDropDown colorDD = new Jonathan.ColorPicker.ToolStripColorDropDown();
            colorDD.ColorPicker.SelectedColorChanged += new EventHandler(ForeColorPicker_SelectedColorChanged);
            this._ForeColorPicker.ButtonClick += new EventHandler(ForeColorPicker_SelectedColorChanged);
            this._ForeColorPicker.DropDown = colorDD;
            Jonathan.ColorPicker.ToolStripColorDropDown colorDD2 = new Jonathan.ColorPicker.ToolStripColorDropDown();
            colorDD2.ColorPicker.Color = Color.Yellow;
            colorDD2.ColorPicker.SelectedColorChanged += new EventHandler(BackColorPicker_SelectedColorChanged);
            this._BackColorPicker.ButtonClick += new EventHandler(BackColorPicker_SelectedColorChanged);
            this._BackColorPicker.DropDown = colorDD2;

            if (this.m_Type.Equals(Common.TYPE_BIBLE, StringComparison.CurrentCultureIgnoreCase))
            {
                this.SetupVersions(version, filePath);

                // Check for Treasury of Scripture Knowledge...
                this.m_TSK = (this.m_FormMain.ProgramData.TSK != null);
            }
            else
            {
                // This is not a bible...
                this.m_tsddVersions.Text = version;
                this.m_tsddVersions.Enabled = false;
                this.toolStripLabel1.Visible = false;
                this.btnQJGo.Visible = false;
                this.txtQJ.Visible = false;
                this.toolStripSeparator2.Visible = false;
                this.m_List.ShowPlusMinus = false;
                this.m_List.ShowRootLines = false;

                if (this.m_Type == Common.TYPE_REFERENCE)
                {
                    this.m_RefList.BringToFront();
                    this.m_RefList.AllowMutltipleSelection = true;
                    this.m_RefList.Visible = true;
                    this.m_List.Visible = false;
                    this.m_RefList.SelectedItemChange += new ListItemChange(RefList_Selection);
                }
            }

            // Events...
            this.m_txtFind.KeyDown += new KeyEventHandler(Find_KeyDown);
            this.txtQJ.KeyDown += new KeyEventHandler(QuickJump_KeyDown);
            this.m_List.AfterSelect += new TreeViewEventHandler(m_List_AfterSelect);
			this.m_WebMain.SetupWebber(main, this);
			this.m_WebSplit.SetupWebber(main, this);
        }

		/// <summary>
		/// Occurs when the Reader Panel is resized.
		/// </summary>
		/// <param name="sender">Reader Panel.</param>
		/// <param name="e">Event Arguments.</param>
        void ReaderPanel_Resize (object sender, EventArgs e)
        {
            this._Working.Top = this.splitContainer1.Panel2.Bottom - this._Working.Height - this.m_tsFind.Height - 10;
            this._Working.Left = (this.splitContainer1.Panel2.Width / 2) - (this._Working.Width / 2);
        }

		/// <summary>
		/// Occurs when this control is fully loaded.
		/// </summary>
		/// <param name="sender">This control.</param>
		/// <param name="e">Event Arguments.</param>
        void ctrlReader_Load (object sender, EventArgs e)
        {
            if (!this.m_Loaded)
                this.LoadBookList(true);
        }

        #endregion

        #region - Get Data -

        /// <summary>
        /// Gets the Type of Book...
        /// </summary>
        /// <param name="path">Path to book.</param>
        private void GetBookType (string path)
        {
            // Create a Query...
            Query q = new Query(QueryType.SELECT, Common.TABLE_INFO);
            q.SELECT("Type");//Abbreviation

            // Run Query...
            Database db = new Database(path);
            db.RunQuery(q);
            this.m_Type = q.Results.GetFieldString(0, 0);
            db.CloseDatabase();
        }

        /// <summary>
        /// Gets the Abbreviations for the bibles...
        /// </summary>
        private void GetBibleAbbrev ()
        {
            this.m_Abbrevation = "";
            string toolTip = "";
            foreach (cJData.icDBInfo dbI in this.m_Versions)
            {
                // Create a Query...
                Query q = new Query(QueryType.SELECT, Common.TABLE_INFO);
                q.SELECT(Common.ABBREVIATION);//Abbreviation

                // Run Query...
                Database db = new Database(dbI.Path);
                toolTip += dbI.Name + " | ";
                db.RunQuery(q);
                if (!string.IsNullOrEmpty(this.m_Abbrevation))
                {
                    this.m_Abbrevation += ", ";
                }
                this.m_Abbrevation += q.Results.GetFieldString(0, 0);
            }
            toolTip = toolTip.Trim().TrimEnd(new char[] { '|' }).Trim();
            this.ToolTip = toolTip;
        }

        /// <summary>
        /// Gets the string representation of the preface(s)...
        /// </summary>
        /// <returns>String of preface info..</returns>
        private string GetPreface ()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<tr>");
            int w = 100 / this.m_Versions.Count;
            foreach (cJData.icDBInfo dbI in this.m_Versions)
            {
                // Create a Query...
                Query q = new Query(QueryType.SELECT, Common.TABLE_INFO);
                q.SELECT("Preface");

                // Run Query...
                Database db = new Database(dbI.Path);
                db.RunQuery(q);
                sb.Append("<td width=\"" + w.ToString() + "%\">");
                sb.Append(q.Results.GetFieldString(0, 0));
                sb.Append("</td>");
            }
            sb.Append("</tr>");

            return sb.ToString();
        }

        #endregion

        #region - Versioning -

        /// <summary>
        /// Sets up the initial version list...
        /// </summary>
        /// <param name="version">Starting version...</param>
        /// <param name="path">Path to version db...</param>
        private void SetupVersions (string version, string path)
        {
            ToolStripMenuItem tsmi = new ToolStripMenuItem(version);
            tsmi.Name = version;
            tsmi.Tag = path;

            ToolStripMenuItem tsmiRemove = new ToolStripMenuItem("Remove Version");
            tsmiRemove.Name = "Remove";
            tsmiRemove.Click += new EventHandler(RemoveVersion_Click);
            tsmi.DropDownItems.Add(tsmiRemove);
            ToolStripMenuItem tsmiChange = new ToolStripMenuItem("Change Version");
            tsmiChange.Name = "Change";
            tsmi.DropDownItems.Add(tsmiChange);

            this.m_tsddVersions.DropDownItems.Add(tsmi);
            this.m_tsddVersions.DropDownItems.Add(new ToolStripSeparator());

            m_tsmiAdd = new ToolStripMenuItem("Add Version");
            this.m_tsddVersions.DropDownOpening += new EventHandler(VersionDropDown_Opening);
            this.m_tsddVersions.DropDownItems.Add(m_tsmiAdd);
        }

        /// <summary>
        /// Occurs when opening the version dropdown...
        /// </summary>
        /// <param name="sender">ToolStripDropDownButton</param>
        /// <param name="e">Events</param>
        void VersionDropDown_Opening (object sender, EventArgs e)
        {
            this.m_tsmiAdd.DropDownItems.Clear();
            foreach (cJData.icDBInfo dbI in this.m_FormMain.ProgramData.BibleDatabases)
            {
                if (!this.m_tsddVersions.DropDownItems.ContainsKey(dbI.Name))
                {
                    ToolStripMenuItem tsmi = new ToolStripMenuItem(dbI.Name);
                    tsmi.Tag = Common.DATA_FOLDER + dbI.Path;
                    tsmi.Click += new EventHandler(AddVersion_Click);
                    this.m_tsmiAdd.DropDownItems.Add(tsmi);
                }
            }

            CheckChangeRemoveVersion();

            if (this.m_tsmiAdd.DropDownItems.Count == 0)
            {
                this.m_tsmiAdd.Enabled = false;
            }
            else
            {
                this.m_tsmiAdd.Enabled = true;
            }
        }

        /// <summary>
        /// Checks to add versions to change to...
        /// </summary>
        private void CheckChangeRemoveVersion ()
        {
            int itemCount = 0;
            for (int a = 0; a < this.m_tsddVersions.DropDownItems.Count; a++)
            {
                if (this.m_tsddVersions.DropDownItems[a].GetType() == typeof(ToolStripSeparator))
                {
                    if (itemCount == 1)
                    {
                        ToolStripMenuItem tsmiR = this.m_tsddVersions.DropDownItems[a - 1] as ToolStripMenuItem;
                        int tsmiRIndex = tsmiR.DropDownItems.IndexOfKey("Remove");
                        ToolStripMenuItem tsmiRemoveO = tsmiR.DropDownItems[tsmiRIndex] as ToolStripMenuItem;
                        tsmiRemoveO.Enabled = false;
                    }
                    break;
                }

                itemCount++;
                ToolStripMenuItem tsmi = this.m_tsddVersions.DropDownItems[a] as ToolStripMenuItem;
                int tsmiIndex = tsmi.DropDownItems.IndexOfKey("Remove");
                ToolStripMenuItem tsmiRemove = tsmi.DropDownItems[tsmiIndex] as ToolStripMenuItem;
                tsmiRemove.Enabled = true;
                tsmiIndex = tsmi.DropDownItems.IndexOfKey("Change");
                ToolStripMenuItem tsmiChange = tsmi.DropDownItems[tsmiIndex] as ToolStripMenuItem;
                tsmiChange.DropDownItems.Clear();

                foreach (ToolStripMenuItem tsmiAdd in this.m_tsmiAdd.DropDownItems)
                {
                    ToolStripMenuItem tsmiNew = new ToolStripMenuItem(tsmiAdd.Text);
                    tsmiNew.Tag = tsmiAdd.Tag;
                    tsmiNew.Click += new EventHandler(ChangeVersion_Click);
                    tsmiChange.DropDownItems.Add(tsmiNew);
                }

                tsmiChange.Enabled = (tsmiChange.DropDownItems.Count > 0);
            }
        }

        /// <summary>
        /// Changes the selected Version...
        /// </summary>
        /// <param name="sender">ToolStripMenuItem</param>
        /// <param name="e">Events</param>
        void ChangeVersion_Click (object sender, EventArgs e)
        {
            ToolStripMenuItem tsmiC = sender as ToolStripMenuItem;
            ToolStripMenuItem tsmi = ((ToolStripMenuItem)tsmiC.OwnerItem).OwnerItem as ToolStripMenuItem;
            foreach (cJData.icDBInfo dbi in this.m_Versions)
            {
                if (dbi.Name == tsmi.Text)
                {
                    dbi.Name = tsmiC.Text;
                    dbi.Path = tsmiC.Tag.ToString();
                    tsmi.Text = tsmiC.Text;
                    tsmi.Name = tsmiC.Text;
                    tsmi.Tag = tsmiC.Tag;
                    break;
                }
            }
            this.LoadBookList(true);
        }

        /// <summary>
        /// Adds the selected Version...
        /// </summary>
        /// <param name="sender">ToolStripMenuItem</param>
        /// <param name="e">Events</param>
        void AddVersion_Click (object sender, EventArgs e)
        {
            ToolStripMenuItem tsmiO = sender as ToolStripMenuItem;
            this.AddVersion(tsmiO.Text, tsmiO.Tag.ToString());
            this.LoadBookList(true);
        }

		/// <summary>
		/// Adds a version to this reader.
		/// </summary>
		/// <param name="version">Name of Version.</param>
		/// <param name="dbPath">Path to version's database.</param>
        public void AddVersion (string version, string dbPath)
        {
            ToolStripMenuItem tsmi = new ToolStripMenuItem(version);
            tsmi.Name = version;
            tsmi.Tag = dbPath;

            ToolStripMenuItem tsmiRemove = new ToolStripMenuItem("Remove Version");
            tsmiRemove.Name = "Remove";
            tsmiRemove.Click += new EventHandler(RemoveVersion_Click);
            tsmi.DropDownItems.Add(tsmiRemove);
            ToolStripMenuItem tsmiChange = new ToolStripMenuItem("Change Version");
            tsmiChange.Name = "Change";
            tsmi.DropDownItems.Add(tsmiChange);

            this.m_tsddVersions.DropDownItems.Insert(this.m_tsddVersions.DropDownItems.Count - 2, tsmi);

            this.m_Versions.Add(new cJData.icDBInfo(dbPath, version));
        }

        /// <summary>
        /// Removes the selected Version...
        /// </summary>
        /// <param name="sender">ToolStripMenuItem</param>
        /// <param name="e">Events</param>
        void RemoveVersion_Click (object sender, EventArgs e)
        {
            ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
            this.m_tsddVersions.DropDownItems.Remove(tsmi.OwnerItem);
            foreach (cJData.icDBInfo dbI in this.m_Versions)
            {
                if (dbI.Name.Equals(tsmi.OwnerItem.Text.ToString()))
                {
                    this.m_Versions.Remove(dbI);
                    break;
                }
            }
            this.LoadBookList(true);
        }

        #endregion

        #region - Load Book List -

        /// <summary>
        /// Loads the list of books in the tree view...
        /// </summary>
        /// <param name="loadPreface">Load the Preface or Not.</param>
        public void LoadBookList (bool loadPreface)
        {
            this.GetBibleAbbrev();

            if (this.m_Type == Common.TYPE_REFERENCE)
            {
                this.LoadReference();
                return;
            }

            Query q = new Query(QueryType.SELECT, Common.TABLE_BOOK_LIST);
            q.SELECT(Common.BOOK_NAME);
            q.SELECT("Order");
            q.SELECT("NumChapters");
            q.ORDERBY("Order", SortDirection.ASCENDING);

            Database db = new Database(this.m_Versions[0].Path);
            db.RunQuery(q);
            //ArrayList selNodes = this.m_List.SelectedNodes;
            int mScrollTop = this.m_WebMain.Document.Body.ScrollTop;
            int sScrollTop = this.m_WebSplit.Document.Body.ScrollTop;
            List<cPassage> selPassages = new List<cPassage>();
            foreach (TreeNode n in this.m_List.SelectedNodes)
            {
                if (n.Parent != null)
                    selPassages.Add(new cPassage(n.Parent.Text, n.Text));
            }
            this.m_List.Nodes.Clear();
            this.m_List.SelectedNodes.Clear();

            for (int a = 0; a < q.RowsReturned; a++)
            {
                TreeNode n = new TreeNode(q.Results.GetFieldString(0, a));
                n.Name = n.Text;

                for (int b = 1; b <= q.Results.GetFieldInt(2, a); b++)
                {
                    n.Nodes.Add(b.ToString());
                }

                this.m_List.Nodes.Add(n);
            }

            if (this.m_Versions.Count > 1)
            {
                SyncBookList();
            }
            if (this.m_List.Nodes.Count == 1)
            {
                this.m_List.Nodes[0].Expand();
            }

            this.m_List.Nodes.Insert(0, Common.PREFACE);
            if (selPassages.Count > 0)
            {
                this.SelectPassages(selPassages);
                this.m_WebMain.Document.Body.ScrollTop = mScrollTop;
                this.m_WebSplit.Document.Body.ScrollTop = sScrollTop;
            }
            else
            {
                if (loadPreface)
                {
                    List<TreeNode> selNodes = new List<TreeNode>();
                    selNodes.Add(this.m_List.Nodes[0]);
                    this.m_List.SelectedNodes = selNodes;
                    this.m_List_AfterSelect(null, null);
                }
            }
            this.m_Loaded = true;
        }

        /// <summary>
        /// Sychronize book list with all versions...
        /// </summary>
        private void SyncBookList ()
        {
            for (int a = 1; a < this.m_Versions.Count; a++)
            {
                Database db = new Database(this.m_Versions[a].Path);
                Query q = new Query(QueryType.SELECT, Common.TABLE_BOOK_LIST);
                q.SELECT("BookName");
                db.RunQuery(q);

                for (int c = this.m_List.Nodes.Count - 1; c >= 0; c--)
                {
                    TreeNode node = this.m_List.Nodes[c];
                    bool inList = false;
                    for (int b = 0; b < q.RowsReturned; b++)
                    {
                        if (q.Results.GetFieldString(0, b).Equals(node.Text))
                        {
                            inList = true;
                            break;
                        }
                    }

                    if (!inList)
                    {
                        this.m_List.Nodes.Remove(node);
                    }
                }
            }
        }

        #endregion

        #region - Tree Selection -

        /// <summary>
        /// Load next information...
        /// </summary>
        /// <param name="sender">Tree Node</param>
        /// <param name="e">Event</param>
        private void m_List_AfterSelect(object sender, TreeViewEventArgs e)
        {
            bool newData = false;
            string tabText = "";
            string lastBook = "";
            // Get nodes...
            List<TreeNode> nodes = this.m_List.SelectedNodes;
            StringBuilder sb = GetHeadingHTML();

            for (int a = 0; a < nodes.Count; a++)
            {
                TreeNode node = (TreeNode)nodes[a];
                if (node.Parent != null)
                {
                    // Create the table...
                    sb.Append(this.GetTable(node.Parent.Text, node.Text));

                    newData = true;

                    if (lastBook.Length == 0)
                    {
                        if (this.m_List.Nodes.Count == 1)
                        {
                            tabText += node.Text;
                        }
                        else
                        {
                            tabText += cParser.GetBook(node.Parent.Text, false) + " " + node.Text;
                        }
                    }
                    else
                    {
                        if (lastBook == node.Parent.Text)
                        {
                            tabText += "," + node.Text;
                        }
                        else
                        {
                            tabText += ";" + cParser.GetBook(node.Parent.Text, false) + " " + node.Text;
                        }
                    }
                    lastBook = node.Parent.Text;
                }
                else
                {
                    if (node.Text == Common.PREFACE)
                    {
                        sb.Append(this.GetPreface());
                        newData = true;
                        lastBook = Common.PREFACE;
                        tabText += Common.PREFACE;
                    }
                }
            }

            sb.Append("</table></div></div></body></html>");

            if (newData)
			{
				// Check to see if the Version's Abbrevation is the same as the Book's...
				if (tabText.Contains(" ") && this.m_Abbrevation.Equals(tabText.Substring(0, tabText.IndexOf(' '))))
					tabText = tabText.Substring(tabText.IndexOf(' ') + 1);
				// If the Tab text is the Same, then we have the same chapters, we can leave and do nothing...
				if(this.TabTitle.Equals(this.m_Abbrevation + " | " + tabText, StringComparison.CurrentCultureIgnoreCase))
					return;
				
				// Set Tab Text...
				this.TabTitle = this.m_Abbrevation + " | " + tabText;
                // Add History...
                this.AddHistory(tabText);

                this.m_WebMain.HTML = sb.ToString();

                if (this.m_Passages != null)
                {
                    HtmlElementCollection els = this.m_WebMain.Document.GetElementsByTagName("tr");
                    for (int z = 0; z < els.Count; z++)
                    {
                        HtmlElement el = els[z];
                        if (!string.IsNullOrEmpty(el.Style) && el.Style.Contains("BACKGROUND-COLOR: yellow"))
                        {
                            el.ScrollIntoView(true);
                            break;
                        }
                    }
                    this.m_Passages = null;
                }

                if (this.m_tsbSplit.Checked)
                {
                    this.m_WebSplit.HTML = sb.ToString();
                }

                this.m_WebMain.Focus();
            }
        }

        #endregion

        #region -= History =-

        /// <summary>
        /// Updates the History for this reader
        /// </summary>
        /// <param name="tabText">Text Found on Tab.</param>
        private void AddHistory (string tabText)
        {
            // Create the History Item...
            string history = "";
            List<string[]> historyTag = new List<string[]>();
            if (this.m_Type == Common.TYPE_REFERENCE)
            {
                history = tabText;
            }
            else
            {
                foreach (cJData.icDBInfo dbi in this.m_Versions)
                {
                    history += dbi.Name + ", ";
                    string[] hTag = new string[2];
                    hTag[0] = dbi.Name;
                    hTag[1] = dbi.Path;
                    historyTag.Add(hTag);
                }
                history = history.Trim().TrimEnd(new char[] { ',' });
                history += " | " + tabText;
            }

            // Check and see if we have the items in history already...
            if (this._btnNavBack.DropDown.Items.ContainsKey(history))
            {
                int index = this._btnNavBack.DropDown.Items.IndexOfKey(history);
                ToolStripMenuItem tsmiOld = (ToolStripMenuItem)this._btnNavBack.DropDown.Items[index];
                if (tsmiOld.Checked)
                    return;

                if (index > 0)
                    this._btnNavForward.Enabled = true;

                this.ClearHistoryChecks();
                tsmiOld.Checked = true;
                return;
            }

            ToolStripMenuItem tsmi = new ToolStripMenuItem(history);
            tsmi.Name = history;
            tsmi.Click += new EventHandler(History_Click);
            tsmi.Tag = historyTag;

            // If we have more than 30, remove the last one...
            if (this._btnNavBack.DropDown.Items.Count == 30)
            {
                this._btnNavBack.DropDown.Items.RemoveAt(29);
            }
            this._btnNavBack.DropDown.Items.Insert(0, tsmi);
            this._btnNavForward.Enabled = false;
            this.ClearHistoryChecks();
            tsmi.Checked = true;
        }

        /// <summary>
        /// Navigate Through History...
        /// </summary>
        /// <param name="sender">ToolStripMenuItem</param>
        /// <param name="e">EventArgs</param>
        void History_Click (object sender, EventArgs e)
        {
            ToolStripMenuItem historyItem = sender as ToolStripMenuItem;
            if (historyItem.Checked)
                return;

            this.SelectHistoryItem(historyItem);
        }

        /// <summary>
        /// Selects the given History Item...
        /// </summary>
        /// <param name="historyItem">Item to select.</param>
        private void SelectHistoryItem (ToolStripMenuItem historyItem)
        {
            this.ClearHistoryChecks();
            historyItem.Checked = true;
            this._btnNavForward.Enabled = (this._btnNavBack.DropDown.Items.IndexOf(historyItem) > 0);

            if (this.m_Type == Common.TYPE_REFERENCE)
            {
                this.SelectRefWords(historyItem.Text.Split(','));
            }
            else if (this.m_Type == Common.TYPE_BIBLE)
            {
                // Check Versions...
                this.CheckHistoryVersions(historyItem);
                string passage = historyItem.Text.Split('|')[1].Trim();
				if(passage.Equals(Common.PREFACE))
					this.m_List.SelectedNode = this.m_List.Nodes[0];
				else
					this.SelectPassages(cParser.Parse(passage));
            }
            else
            {
                string chapters = historyItem.Text.Split('|')[1].Trim();
				//chapters = chapters.Substring(chapters.IndexOf(" ")).Trim();
                this.SelectChapter(1, chapters.Split(','));
            }
        }

        /// <summary>
        /// Check to see if we need to update the version when we change history...
        /// </summary>
        /// <param name="historyItem">History Item in question.</param>
        private void CheckHistoryVersions (ToolStripMenuItem historyItem)
        {
            bool newVersion = false;
            List<string[]> versions = (List<string[]>)historyItem.Tag;

            // Check if we need to add versions...
            foreach (string[] version in versions)
            {
                bool found = false;
                foreach (cJData.icDBInfo v in this.m_Versions)
                {
                    if (v.Path.Equals(version[1]))
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    newVersion = true;
                    break;
                }
            }

            if (!newVersion)
            {
                // Check if we need to remove versions...
                foreach (cJData.icDBInfo version in this.m_Versions)
                {
                    bool found = false;
                    foreach (string[] v in versions)
                    {
                        if (v[1].Equals(version.Path))
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        newVersion = true;
                        break;
                    }
                }
            }

            if (newVersion)
            {
                // Change the Versions...
                this.m_tsddVersions.DropDownItems.Clear();
                this.m_Versions.Clear();
                foreach (string[] version in versions)
                {
                    if (this.m_tsddVersions.DropDownItems.Count == 0)
                    {
                        this.m_Versions.Add(new cJData.icDBInfo(version[1], version[0]));
                        this.SetupVersions(version[0], version[1]);
                    }
                    else
                        this.AddVersion(version[0], version[1]);
                }
                this.LoadBookList(false);
            }
        }

        /// <summary>
        /// Navigate Backward Through History...
        /// </summary>
        /// <param name="sender">ToolStripMenuButton</param>
        /// <param name="e">EventArgs</param>
        void NavHistoryBack_Click (object sender, EventArgs e)
        {
            int currIndex = this.GetSelectedHistoryItemIndex();
            if (currIndex == this._btnNavBack.DropDown.Items.Count - 1)
                return;
            else
            {
                this.SelectHistoryItem((ToolStripMenuItem)this._btnNavBack.DropDown.Items[currIndex + 1]);
            }
        }

        /// <summary>
        /// Navigate Forward Through History...
        /// </summary>
        /// <param name="sender">ToolStripMenuButton</param>
        /// <param name="e">EventArgs</param>
        void NavHistoryForward_Click (object sender, EventArgs e)
        {
            int currIndex = this.GetSelectedHistoryItemIndex();
            if(currIndex > 0)
                this.SelectHistoryItem((ToolStripMenuItem)this._btnNavBack.DropDown.Items[currIndex - 1]);
        }

        /// <summary>
        /// Gets the Selected History Item...
        /// </summary>
        /// <returns>Index of Selected History Item.</returns>
        private int GetSelectedHistoryItemIndex ()
        {
            int count = 0;
            foreach (ToolStripMenuItem tsmi in this._btnNavBack.DropDown.Items)
            {
                if (tsmi.Checked)
                {
                    return count;
                }
                count++;
            }

            return -1;
        }

        /// <summary>
        /// Clears all the Checks on the History Items
        /// </summary>
        private void ClearHistoryChecks ()
        {
            foreach (ToolStripMenuItem tsmi in this._btnNavBack.DropDown.Items)
            {
                tsmi.Checked = false;
            }
        }

        #endregion

        #region -= Get Heading HTML =-

        /// <summary>
        /// Gets the Heading HTML for displaying data...
        /// </summary>
        /// <returns>String Builder with heading html.</returns>
        private StringBuilder GetHeadingHTML ()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(this.m_FormMain.GetHtmlHeader());
            sb.Append("<div id=\"reader\"><div id=\"readerTitles\"><table width=\"100%\">");
            int w = 100 / this.m_Versions.Count;
            for (int a = 0; a < this.m_Versions.Count; a++)
            {
                sb.Append("<col width=\"" + w.ToString() + "%\">");
            }

            sb.Append("<tr>");

            foreach (cJData.icDBInfo dbI in this.m_Versions)
            {
                sb.Append("<th align=\"center\" width=\"" + w.ToString() + "%\" style=\"filter:progid:DXImageTransform.Microsoft.Gradient(endColorstr='#0060A5', startColorstr='#C0CFE2', gradientType='0');color:white;\">");
                sb.Append(dbI.Name);
                sb.Append("</th>");
            }

            sb.Append("</tr></table></div>");
            sb.Append("<div id=\"innerReader\"><table width=\"100%\">");
            if (this.m_TSK)
                sb.Append("<col width=\"25px\">");
            sb.Append("<col width=\"3%\">");
            for (int a = 0; a < this.m_Versions.Count; a++)
            {
                sb.Append("<col width=\"" + w.ToString() + "%\">");
            }
            sb.Append("<col width=\"3%\">");

            return sb;
        }

        #endregion

        #region - Reference -

        /// <summary>
        /// Loads the Reference Words...
        /// </summary>
        private void LoadReference ()
        {
            StringBuilder sb = this.GetHeadingHTML();
            sb.Append(this.GetPreface());
            sb.Append("</table></div></div></body></html>");
            this.m_WebMain.HTML = this.m_WebSplit.HTML = sb.ToString();

            this._Working.SetText("Loading Reference List...");
            this._Working.Visible = true;
            this.m_RefList.Items.Clear();
            Thread t = new Thread(new ThreadStart(LoadReferenceThread));
            t.Start();
        }

        /// <summary>
        /// Loads the Reference Words...
        /// </summary>
        private void LoadReferenceThread ()
        {
            Database db = new Database(this.m_Versions[0].Path);
            string[] tables = db.TableList.Split(';');
            List<string> words = new List<string>();

            Query qBookList = new Query(QueryType.SELECT, Common.TABLE_BOOK_LIST);
            qBookList.SELECT("*");
            db.RunQuery(qBookList);

            for(int b = 0; b < qBookList.RowsReturned; b++)
            {
                string table = qBookList.Results.GetFieldString(0, b);
                Query q = new Query(QueryType.SELECT, table);
                q.SELECT("Word");

                db.RunQuery(q);

                for (int a = 0; a < q.RowsReturned; a++)
                {
                    words.Add(q.Results.GetFieldString(0, a));
                }
            }
            if(!qBookList.Results.GetFieldString(3, 0).Equals("NOSORT"))
                words.Sort();
            this.Invoke(this.m_AddRef, new object[] { Common.PREFACE });
            foreach (string word in words)
            {
                this.Invoke(this.m_AddRef, new object[] { word });
            }
            this.Invoke(this.m_RefLoaded);
        }

        /// <summary>
        /// Occurs when an Item in the list is selected...
        /// </summary>
        /// <param name="sender">ListItem</param>
        /// <param name="e">Events</param>
        void RefList_Selection (object sender, EventArgs e)
        {
            ListItemCollection items = this.m_RefList.SelectedItems;//.SelectedText;
            StringBuilder sb = this.GetHeadingHTML();

            if (this.m_RefList.SelectedIndex == 0)
            {
                this.TabTitle = this.m_Abbrevation + " | " + Common.PREFACE;
                sb.Append(this.GetPreface());
                this.AddHistory(Common.PREFACE);
            }
            else
            {
                string tabText = this.m_Abbrevation + " | ";
                foreach (ListItem li in items)
                {
                    Database db = new Database(this.m_Versions[0].Path);
                    Query qBookList = new Query(QueryType.SELECT, Common.TABLE_BOOK_LIST);
                    qBookList.SELECT("*");
                    db.RunQuery(qBookList);

                    Query q = new Query(QueryType.SELECT, li.Text[0].ToString());
                    if (qBookList.RowsReturned == 1)
                        q.Table = qBookList.Results.GetFieldString(0, 0);
                    q.SELECT("*");
                    q.WHERE("Word", Operator.EQUALS, li.Text);

                    db.RunQuery(q);

                    tabText += li.Text + ",";
                    sb.Append("<tr><td><h3>" + li.Text + "</h3>");
                    if (!string.IsNullOrEmpty(q.Results.GetFieldString(2, 0)))
                    {
                        sb.Append("(" + q.Results.GetFieldString(2, 0) + ")");
                    }
                    sb.Append("</td></tr><tr><td>");
                    sb.Append(q.Results.GetFieldString(1, 0));
                    sb.Append("</td></tr>");
                }
                tabText = tabText.TrimEnd(new char[] { ',' });

				if (this.TabTitle.Equals(tabText))
					return;
                this.TabTitle = tabText;
                this.AddHistory(tabText.Split('|')[1].Trim());
            }
            sb.Append("</table></div></div></body></html>");

            this.m_WebMain.HTML = sb.ToString();
            if (this.m_tsbSplit.Checked)
            {
                this.m_WebSplit.HTML = sb.ToString();
            }
        }

        /// <summary>
        /// Selectes the given Reference word...
        /// </summary>
        /// <param name="word">Word to Select.</param>
		/// <param name="tryContains">Check if one of the list items contains the word.</param>
		/// <returns>True if word was selected, otherwise false</returns>
        public bool SelectRefWord (string word, bool tryContains)
        {
            foreach (ListItem li in this.m_RefList.Items)
            {
                if (li.Text.Equals(word, StringComparison.CurrentCultureIgnoreCase))
                {
                    this.m_RefList.SelectedItem = li;
                    return true;
                }
            }
			if (!this.m_Loaded)
			{
				cPassage p = new cPassage(word, "1");
				this.m_Passages = new List<cPassage>();
				this.m_Passages.Add(p);
			}
			if (tryContains)
			{
				foreach (ListItem li in this.m_RefList.Items)
				{
					if (li.Text.ToLower().Contains(word.ToLower()))
					{
						this.m_RefList.SelectedItem = li;
						return true;
					}
				}
			}

			return false;
        }

        /// <summary>
        /// Selectes the given Reference words...
        /// </summary>
        /// <param name="words">Words to Select.</param>
        public void SelectRefWords (string[] words)
        {
            ListItemCollection lic = new ListItemCollection(this.m_RefList);

            foreach (ListItem li in this.m_RefList.Items)
            {
                foreach (string word in words)
                {
                    if (li.Text.Equals(word))
                    {
                        lic.Add(li);
                    }
                }
            }

            this.m_RefList.SelectedItems = lic;
            if (!this.m_Loaded)
            {
                this.m_Passages = new List<cPassage>();
                foreach (string word in words)
                {
                    cPassage p = new cPassage(word, "1");
                    this.m_Passages.Add(p);
                }
            }
		}

		/// <summary>
		/// Add the given word to the reference list...
		/// </summary>
		/// <param name="word">Word to add</param>
		private void AddRefWord (string word)
		{
			this.m_RefList.Items.Add(new ListItem(word));
			Application.DoEvents();
		}

        /// <summary>
        /// Handles some finishing routines for loading Reference...
        /// </summary>
        private void RefLoaded ()
        {
			if (this.m_Passages != null)
			{
				ListItemCollection lic = new ListItemCollection(this.m_RefList);
				foreach (cPassage passage in this.m_Passages)
				{
					foreach (ListItem li in this.m_RefList.Items)
					{
						if (passage.Book.Equals(li.Text))
						{
							lic.Add(li);
							break;
						}
					}
				}
				this.m_RefList.SelectedItems = lic;
				this.m_Passages.Clear();
				this.m_Passages = null;
			}
			else
			{
				this.m_RefList.Items[0].Selected = true;
				this.m_RefList.Refresh();
			}
            this._Working.Visible = false;
        }

        #endregion

        #region - Get Table (string) -

        /// <summary>
        /// Create an HTML Table with the given results
        /// </summary>
		/// <param name="book">Book to get Table for</param>
		/// <param name="chapter">Chapter to get table for</param>
        /// <returns>html table string.</returns>
        private string GetTable(string book, string chapter)
        {
            List<Results> dbResults = new List<Results>();
            int rowCount = 0;

            // Get results for each version...
            foreach (cJData.icDBInfo dbI in this.m_Versions)
            {
                // Get info from db...
                Query q = new Query(QueryType.SELECT, book);
                q.SELECT("*");
                q.WHERE("Chapter", Operator.EQUALS, Convert.ToInt32(chapter));
                q.ORDERBY("Verse", SortDirection.ASCENDING);

                Database db = new Database(dbI.Path);
                db.RunQuery(q);
                rowCount = (rowCount > q.RowsReturned) ? rowCount : q.RowsReturned;
                dbResults.Add(q.Results);
            }

            Database dbVerseNotes = new Database(Common.DATA_FOLDER + Common.DATABASE_VERSE_NOTES);
            Query qVerseNotes = new Query(QueryType.SELECT, Common.TABLE_NOTES);
            qVerseNotes.SELECT("Verse");
            qVerseNotes.SELECT("Note");
            qVerseNotes.WHERE("Book", Operator.EQUALS, book);
            qVerseNotes.WHERE("Chapter", Operator.EQUALS, chapter);
            dbVerseNotes.RunQuery(qVerseNotes);

            // Build Results...
            if (dbResults.Count > 0)
            {
                // Build Table...
                StringBuilder sb = new StringBuilder();
                sb.Append("<tr>");
                int tds = (this.m_TSK) ? 3 : 2;
                sb.Append("<th colspan=\"" + Convert.ToString(tds + dbResults.Count) + "\" align=\"center\" style=\"filter:progid:DXImageTransform.Microsoft.Gradient(endColorstr='#D8D8D8', startColorstr='#FFFFFF', gradientType='0');\">");
                sb.Append(book + ((book.IndexOf("Psalm") == 0) ? " " : " Chapter ") + chapter);
                sb.Append("</th>");
                sb.Append("</tr>");
                int verse = 1;

                // Get Width of each cell...
                int tdWidth = 100 / dbResults.Count;
                // Loop throught results...
                for (int a = 0; a < rowCount; a++)
                {
                    // Check if we have any headers...
                    GetHeaderFooter(dbResults, sb, a, 3, this.m_TSK);

                    // Chapter:Verse Label...
                    bool temp = false;
                    if (this.m_Passages != null)
                    {
                        foreach (cPassage pass in this.m_Passages)
                        {
                            if (pass.Book == book && pass.Verse != null)
                            {
                                if (pass.Chapter == chapter && pass.Verse == verse.ToString())
                                {
                                    temp = true;
                                }
                            }
                        }
                    }

                    sb.Append("<tr passage=\"" + book + "|" + chapter + "|" + verse.ToString() + "\"");
                    sb.Append("onMouseOver=\"this.className='highliteRow'\" onMouseOut=\"this.className='normalRow'\"");
                    if (temp)
                        sb.Append(" style=\"background-color:yellow;\"");

                    sb.Append(">");

                    if (this.m_TSK)
                    {
                        sb.Append("<td valign=\"top\" align=\"right\">");
                        sb.Append("<div title=\"Treasury of Scripture Knowledge\" style=\"font-size:70%;cursor:hand;border:0px;\" destina=\"tsk|" +
                            book + "|" + chapter + "|" + verse.ToString() + "\">TSK</div>");
                        sb.Append("</td>");
                    }

                    sb.Append("<td class=\"passage\" valign=\"top\" align=\"right\">");
                    sb.Append(chapter + ":" + verse.ToString());
                    sb.Append("</td>");

                    // Add Text...
                    int version = 0;
                    foreach (Results r in dbResults)
                    {
                        sb.Append("<td align=\"left\" valign=\"top\" version=\"" + version.ToString() + "\">");
                        sb.Append(r.GetFieldString(2, a));
                        sb.Append("</td>");
                        version++;
                    }

                    // Chapter:Verse Label...
                    sb.Append("<td class=\"passage\" valign=\"top\" align=\"left\">");
                    sb.Append(chapter + ":" + verse.ToString());
                    sb.Append("</td>");

                    sb.Append("</tr>");

                    if (this.m_TSK)
                    {
                        sb.Append("<tr style=\"display:none\"><td></td><td></td><td colspan=\"" + Convert.ToString(dbResults.Count) +
                            "\" align=\"center\" version=\"0\"><div id=\"tsk|" + book + "|" + chapter + "|" + verse.ToString() + 
                            "\"></div></td><td></td></tr>");
                    }

                    // Add Notes...
                    string note = "";
                    for (int z = 0; z < qVerseNotes.RowsReturned; z++)
                    {
                        if (qVerseNotes.Results.GetFieldString(0, z).Equals(verse.ToString()))
                        {
                            note = qVerseNotes.Results.GetFieldString(1, z);
                        }
                    }
                    if(string.IsNullOrEmpty(note))
                    {
                        sb.Append("<tr style=\"display:none\"><td></td><td></td><td colspan=\"" + Convert.ToString(dbResults.Count) +
                            "\" align=\"center\" version=\"0\"><div id=\"note|" + book + "|" + chapter + "|" + verse.ToString() + "\">");
                    }
                    else
                    {
                        sb.Append("<tr><td style=\"BACKGROUND: #D8D8D8\"><span style=\"writing-mode: tb-rl;filter: flipv fliph;font-weight:bold;\">Notes</span></td><td></td><td colspan=\"" + 
                            Convert.ToString(dbResults.Count) + "\" align=\"left\" version=\"0\"><div id=\"note|" + book + "|" + chapter + "|" + verse.ToString() + "\">");
                        sb.Append(note);
                    }
                    sb.Append("</div></td><td></td></tr>");

                    // Check for footer...
                    GetHeaderFooter(dbResults, sb, a, 4, this.m_TSK);
                    verse++;
                }

                return sb.ToString();
            }
            return "";
        }

        /// <summary>
        /// Gets the header or footer...
        /// </summary>
        /// <param name="dbResults">DB information</param>
        /// <param name="sb">StringBuilder.</param>
        /// <param name="row">Row for Info.</param>
        /// <param name="col">Column for Info.</param>
        private static void GetHeaderFooter (List<Results> dbResults, StringBuilder sb, int row, int col, bool tsk)
        {
            bool temp = false;
            int version = 0;
            foreach (Results r in dbResults)
            {
                if (!string.IsNullOrEmpty(r.GetFieldString(col, row)))
                {
                    temp = true;
                    break;
                }
            }
            if (temp)
            {
                // Add Headers...
                sb.Append("<tr><td>&nbsp;</td>");
                if (tsk)
                    sb.Append("<td>&nbsp;</td>");
                foreach (Results r in dbResults)
				{
					if (col == 4)
					{
						sb.Append("<td align=\"left\" version=\"" + version.ToString() + "\">");
						sb.Append("<blockquote><small>" + r.GetFieldString(col, row) + "</small></blockquote>");
					}
					else
					{
						sb.Append("<td align=\"center\" version=\"" + version.ToString() + "\">");
						sb.Append("<small>" + r.GetFieldString(col, row) + "</small><br/>");
					}
                    sb.Append("</td>");
                    version++;
                }
                sb.Append("<td>&nbsp;</td></tr>");
            }
        }

        #endregion

        #region - Show/Hide Book List -

        /// <summary>
        /// Shows or hides the book list
        /// </summary>
        /// <param name="sender">Button</param>
        /// <param name="e">Events</param>
        private void m_tsbHidBookList_Click(object sender, EventArgs e)
        {
            if (this.m_tsbHidBookList.Text == "Hide List")
            {
                this.splitContainer1.Panel1Collapsed = true;
                this.m_tsbHidBookList.Text = "Show List";
            }
            else
            {
                this.splitContainer1.Panel1Collapsed = false;
                this.m_tsbHidBookList.Text = "Hide List";
            }
        }

        #endregion

        #region - Find Next -

        /// <summary>
        /// Finds the next occurance of the requested string...
        /// </summary>
        /// <param name="sender">Button</param>
        /// <param name="e">Event</param>
        private void m_tsbFind_Click(object sender, EventArgs e)
        {
            if (this.m_txtFind.Text.Trim() != string.Empty)
            {
                this.m_WebMain.FindNext(this.m_txtFind.Text);
            }
        }

        /// <summary>
        /// Occurs when a key stroke happens in the find text...
        /// </summary>
        /// <param name="sender">Find TextBox</param>
        /// <param name="e">Events</param>
        void Find_KeyDown (object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                this.m_tsbFind_Click(sender, null);
        }

        #endregion

        #region - Split View -

        /// <summary>
        /// Shows or Hides the Split view...
        /// </summary>
        /// <param name="sender">Button</param>
        /// <param name="e">Event</param>
        private void m_tsbSplit_Click(object sender, EventArgs e)
        {
            this.m_SplitRead.Panel2Collapsed = !this.m_tsbSplit.Checked;
            if (this.m_tsbSplit.Checked)
            {
                this.m_WebSplit.HTML = this.m_WebMain.HTML;
            }
        }

        #endregion

        #region - Select Chapter -

        /// <summary>
        /// Selects the Next Chapter...
        /// </summary>
        /// <param name="sender">ToolStripButton</param>
        /// <param name="e">Events</param>
        private void btnNextChapter_Click (object sender, EventArgs e)
        {
            if (this.m_Type == Common.TYPE_REFERENCE)
            {
                if (this.m_RefList.Items.Count > 0)
                {
                    int selIndex = this.m_RefList.SelectedIndex + 1;
                    if (selIndex >= this.m_RefList.Items.Count)
                    {
                        this.m_RefList.SelectedIndex = 0;
                    }
                    else
                    {
                        this.m_RefList.SelectedIndex = selIndex;
                    }
                }
            }
            else
            {
                if (this.m_List.SelectedNode == null)
                {
                    this.SelectFirstChapter();
                }
                else
                {
                    if (this.m_List.SelectedNode.Parent == null)
                    {
                        this.m_List.SelectedNode = this.m_List.SelectedNode.FirstNode;
                    }
                    else
                    {
                        if (this.m_List.SelectedNode.NextNode == null)
                        {
                            if (this.m_List.SelectedNode.Parent.NextNode != null && this.m_List.SelectedNode.Parent.NextNode.Nodes.Count > 0)
                            {
                                this.m_List.SelectedNode = this.m_List.SelectedNode.Parent.NextNode.FirstNode;
                            }
                            else
                            {
                                this.SelectFirstChapter();
                            }
                        }
                        else
                            this.m_List.SelectedNode = this.m_List.SelectedNode.NextNode;
                    }
                }
            }
        }

        /// <summary>
        /// Selects the Previous Chapter...
        /// </summary>
        /// <param name="sender">ToolStripButton</param>
        /// <param name="e">Events</param>
        private void btnPreviousChapter_Click (object sender, EventArgs e)
        {
            if (this.m_Type == Common.TYPE_REFERENCE)
            {
                if (this.m_RefList.Items.Count > 0)
                {
                    int selIndex = this.m_RefList.SelectedIndex - 1;
                    if (selIndex < 0)
                    {
                        this.m_RefList.SelectedIndex = this.m_RefList.Items.Count - 1;
                    }
                    else
                    {
                        this.m_RefList.SelectedIndex = selIndex;
                    }
                }
            }
            else
            {
                if (this.m_List.SelectedNode == null)
                {
                    this.SelectFirstChapter();
                }
                else
                {
                    if (this.m_List.SelectedNode.Parent == null)
                    {
                        this.m_List.SelectedNode = this.m_List.SelectedNode.FirstNode;
                    }
                    else
                    {
                        if (this.m_List.SelectedNode.PrevNode == null)
                        {
                            if (this.m_List.SelectedNode.Parent.PrevNode != null && this.m_List.SelectedNode.Parent.PrevNode.Nodes.Count > 0)
                            {
                                this.m_List.SelectedNode = this.m_List.SelectedNode.Parent.PrevNode.LastNode;
                            }
                            else
                            {
                                this.SelectLastChapter();
                            }
                        }
                        else
                            this.m_List.SelectedNode = this.m_List.SelectedNode.PrevNode;
                    }
                }
            }
        }

        /// <summary>
        /// Selects the very first Chapter in the list...
        /// </summary>
        private void SelectFirstChapter ()
        {
            foreach (TreeNode node in this.m_List.Nodes)
            {
                if (node.Nodes.Count > 0)
                {
                    this.m_List.SelectedNode = node.Nodes[0];
                    break;
                }
            }
        }

        /// <summary>
        /// Selectes the very last Chapter in the list...
        /// </summary>
        private void SelectLastChapter ()
        {
            if (this.m_List.Nodes.Count > 0)
                if (this.m_List.Nodes[this.m_List.Nodes.Count - 1].Nodes.Count > 0)
                    this.m_List.SelectedNode = this.m_List.Nodes[this.m_List.Nodes.Count - 1].LastNode;
        }

        /// <summary>
        /// Selectes the given chapter in the given node...
        /// </summary>
        /// <param name="node">Node that contains chapter.</param>
        /// <param name="chap">Chapter to select.</param>
        public void SelectChapter (int node, string[] chaps)
        {
            if (this.m_List.Nodes.Count > node && node >= 0)
            {
                this.m_List.ClearSelection();
                List<TreeNode> selNodes = new List<TreeNode>();
                foreach (string chap in chaps)
                {
                    if (chap.Equals(Common.PREFACE))
                    {
                        selNodes.Add(this.m_List.Nodes[0]);
                    }
                    else
                    {
                        selNodes.Add(this.m_List.Nodes[node].Nodes[Convert.ToInt32(chap) - 1]);
                    }
                }
                this.m_List.SelectedNodes = selNodes;
                this.m_List_AfterSelect(null, null);
            }
        }

        #endregion

        #region - Quick Jump -

        /// <summary>
        /// Occurs when a key stroke happens in the Quick Jump text...
        /// </summary>
        /// <param name="sender">Quick Jump TextBox</param>
        /// <param name="e">Events</param>
        void QuickJump_KeyDown (object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                this.btnQJGo_Click(sender, null);
        }

        /// <summary>
        /// Parses the List of Passages in the Quick Jump TextBox...
        /// </summary>
        /// <param name="sender">ToolStripButton</param>
        /// <param name="e">Events</param>
        private void btnQJGo_Click (object sender, EventArgs e)
        {
            List<cPassage> passages = cParser.Parse(txtQJ.Text);
            SelectPassages(passages);
        }

        /// <summary>
        /// Selects the List of Given Passages...
        /// </summary>
        /// <param name="passages">List of Passages to Select.</param>
        public void SelectPassages (List<cPassage> passages)
        {
            this.CheckVersions(passages);
            this.m_List.ClearSelection();

            List<TreeNode> selNodes = new List<TreeNode>();
            foreach (TreeNode root in this.m_List.Nodes)
            {
                foreach (cPassage passage in passages)
                {
                    if (root.Text.Equals(passage.Book))
                    {
                        foreach (TreeNode node in root.Nodes)
                        {
                            if (node.Text.Equals(passage.Chapter))
                            {
                                root.Expand();
                                if (!selNodes.Contains(node))
                                {
                                    selNodes.Add(node);
                                }
                            }
                        }
                    }
                }
            }

            this.m_Passages = passages;
            if (selNodes.Count > 0)
            {
                this.m_List.GroupAdd = true;
                this.m_List.SelectedNodes = selNodes;
                this.m_List.SelectedNode = selNodes[0];
                //this.m_List_AfterSelect(null, null);
            }
        }

        /// <summary>
        /// Checks to see if we have all the versions needed...
        /// </summary>
        /// <param name="passages">List of passages with versions.</param>
        private void CheckVersions (List<cPassage> passages)
        {
            int addVersion = 0;
            List<string> versions = new List<string>();
            foreach (cPassage passage in passages)
            {
                if (!string.IsNullOrEmpty(passage.Version))
                {
                    versions.Add(passage.Version);
                }
            }
            if (versions.Count > 0)
            {
                foreach (string version in versions)
                {
                    bool hasVersion = false;
                    foreach (cJData.icDBInfo dbi in this.m_Versions)
                    {
                        if (dbi.Name.Equals(version))
                        {
                            hasVersion = true;
                            break;
                        }
                    }
                    if (!hasVersion)
                    {
                        this.AddVersion(version, this.m_FormMain.GetDBPath(version));
                        addVersion++;
                    }
                }
            }

            if (addVersion > 0)
                this.LoadBookList(true);
        }

        #endregion

        #region - Random Chapter -

        private void GenerateRandomChapter (object sender, System.EventArgs e)
        {
            try
            {
                Random rand = new Random(System.DateTime.Now.Millisecond);
                // Get Book...
                TreeNode book = this.m_List.Nodes[rand.Next(this.m_List.Nodes.Count)];

                TreeNode chap = book.Nodes[rand.Next(book.Nodes.Count)];
                this.m_List.SelectedNode = chap;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                this.GenerateRandomChapter(sender, e);
            }
        }

        #endregion

        #region - MISC -

        /// <summary>
        /// Gets the Current Book...
        /// </summary>
        public string Book
        {
            get
            {
                string book = "";
                if (this.m_Type != Common.TYPE_REFERENCE)
                {
                    if (this.m_List.SelectedNode.Parent == null)
                    {
                        if (this.m_List.SelectedNode.Text != Common.PREFACE)
                        {
                            book = this.m_List.SelectedNode.Text;
                        }
                    }
                    else
                    {
                        book = this.m_List.SelectedNode.Parent.Text;
                    }
                }
                return book;
            }
        }

        /// <summary>
        /// Gets the first webber that has a selection...
        /// </summary>
        /// <returns>Webber with Selection</returns>
        private Webber GetWebber ()
        {
            if (!string.IsNullOrEmpty(this.m_WebMain.Selection))
                return this.m_WebMain;

            if (this.m_tsbSplit.Checked)
            {
                if (!string.IsNullOrEmpty(this.m_WebSplit.Selection))
                    return this.m_WebSplit;
            }

            return null;
        }

        /// <summary>
        /// Gets the Webber associated with the context menu item...
        /// </summary>
        /// <param name="tsmi">ToolStripMenuItem in context menu...</param>
        /// <returns>Webber</returns>
        private Webber GetWebber (ToolStripMenuItem tsmi)
        {
            ContextMenuStrip ctx = tsmi.Owner as ContextMenuStrip;
            if (ctx.SourceControl.Name.Equals("m_WebSplit"))
                return this.m_WebSplit;
            else
                return this.m_WebMain;
        }
        
        /// <summary>
        /// Gets the Page Info...
        /// </summary>
        /// <returns>Tabber Page Info.</returns>
        public override string GetPageInfo ()
        {
            string versionInfo = "";
            foreach (cJData.icDBInfo dbi in this.m_Versions)
            {
                versionInfo += dbi.Name + "|" + dbi.Path + "|";
            }
            return versionInfo;
        }

        /// <summary>
        /// Gets the Type of Reader...
        /// </summary>
        public string ReaderType
        {
            get { return this.m_Type; }
        }

        /// <summary>
        /// Get the name of the given version...
        /// </summary>
        /// <param name="version">Version Index.</param>
        /// <returns>Version Name.</returns>
        public string GetVersion (int version)
        {
            if (version >= 0 && version < this.m_Versions.Count)
                return this.m_Versions[version].Name;
            else if (version == -1 && this.m_Versions.Count == 1 && this.m_Type != Common.TYPE_REFERENCE)
                return this.m_Versions[0].Name;
            else
                return "";
        }

        /// <summary>
        /// Gets the Path of the given version
        /// </summary>
        /// <param name="version">Version Index.</param>
        /// <returns>Version Path.</returns>
        public string GetVersionPath (int version)
        {
            if (version >= 0 && version < this.m_Versions.Count)
                return this.m_Versions[version].Path;
            else if (version == -1 && this.m_Versions.Count == 1 && this.m_Type != Common.TYPE_REFERENCE)
                return this.m_Versions[0].Path;
            else
                return "";
        }

        /// <summary>
        /// Gets the TabberPage associated with the host...
        /// </summary>
        /// <returns>TabberPage</returns>
        public Tabber.TabberPage GetTabPage ()
        {
            return this;
        }

        /// <summary>
        /// A Method to update the Font...
        /// </summary>
        public void UpdateText ()
        {
            this.m_List_AfterSelect(null, null);
        }

        #endregion

        #region - Context Menu -

		/// <summary>
		/// Gets the Context Menu for this control.
		/// </summary>
		/// <returns>Context Menu for this control.</returns>
        public ContextMenuStrip GetContextMenu ()
        {
            // Create a new Context Menu...
            System.Windows.Forms.ContextMenuStrip ctx = new ContextMenuStrip();
            ctx.Opening += new CancelEventHandler(ctx_Opening);

            // Copy...
            ToolStripMenuItem tsmiCopy = new ToolStripMenuItem("Copy");
            tsmiCopy.Click += new EventHandler(Copy_Click);
            tsmiCopy.Name = "copy";
            tsmiCopy.Image = this.m_FormMain.GetInternalImage("CopyHS");
            // Copy Verse...
            ToolStripMenuItem tsmiCopyV = new ToolStripMenuItem("Copy Verse");
            tsmiCopyV.Click += new EventHandler(CopyV_Click);
            tsmiCopyV.Image = this.m_FormMain.GetInternalImage("_goto");
            tsmiCopyV.Name = "vcopy";
            if (this.m_Type == Common.TYPE_REFERENCE)
                tsmiCopyV.Enabled = false;
            // Search...
            ToolStripMenuItem tsmiSearch = new ToolStripMenuItem("Search");
            tsmiSearch.Click += new EventHandler(Search_Click);
            tsmiSearch.Name = "search";
            tsmiSearch.Image = this.m_FormMain.GetInternalImage("searchmag");
            // Define...
            ToolStripMenuItem tsmiDefine = new ToolStripMenuItem("Lookup Definitions");
            tsmiDefine.Click += new EventHandler(Define_Click);
            tsmiDefine.Name = "define";
            // BookMark...
            ToolStripMenuItem tsmiBookMark = new ToolStripMenuItem("Book Mark");
            tsmiBookMark.Click += new EventHandler(BookMark_Click);
            tsmiBookMark.Image = this.m_FormMain.GetInternalImage("bible");
            tsmiBookMark.Name = "bookmark";
            // Verse Notes...
            ToolStripMenuItem tsmiNotes = new ToolStripMenuItem("Add/Edit Verse Notes");
            tsmiNotes.Click += new EventHandler(Note_Click);
            tsmiNotes.Image = this.m_FormMain.GetInternalImage("NoteHS");
            tsmiNotes.Name = "note";

            ctx.Items.Add(tsmiCopy);
            ctx.Items.Add(new ToolStripSeparator());
            ctx.Items.Add(tsmiCopyV);
            ctx.Items.Add(tsmiBookMark);
            ctx.Items.Add(tsmiNotes);
            ctx.Items.Add(new ToolStripSeparator());
            ctx.Items.Add(tsmiSearch);
            ctx.Items.Add(tsmiDefine);

            return ctx;
        }

        /// <summary>
        /// Activates the Copy Command...
        /// </summary>
        /// <param name="sender">ToolStripMenuItem</param>
        /// <param name="e">EventArgs</param>
        void Copy_Click (object sender, EventArgs e)
        {
            ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
            this.GetWebber(tsmi).Copy();
        }

        /// <summary>
        /// Copies the given verse...
        /// </summary>
        /// <param name="sender">ToolStripMenuItem</param>
        /// <param name="e">EventArgs</param>
        void CopyV_Click (object sender, EventArgs e)
        {
            ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
            Clipboard.SetText(tsmi.Tag.ToString());
        }

        /// <summary>
        /// Adds a book mark...
        /// </summary>
        /// <param name="sender">ToolStripMenuItem</param>
        /// <param name="e">EventArgs</param>
        void BookMark_Click (object sender, EventArgs e)
        {
            ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
            this.m_FormMain.AddBookMark(tsmi.Tag.ToString());
        }

        /// <summary>
        /// Add/Edit Verse Notes...
        /// </summary>
        /// <param name="sender">ToolStripMenuItem</param>
        /// <param name="e">EventArgs</param>
        void Note_Click (object sender, EventArgs e)
        {
            ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
			Webber web = this.GetWebber(tsmi);
			//HtmlElement elTD = this.GetTDElement(web);
			//if (elTD == null) return;
			HtmlElement elTR = Common.GetTRElement(web);//web.GetParentElement(elTD, "TR");
            
            if (elTR != null)
            {
                int index = 0;
                string dest = "";
                if ((index = elTR.FirstChild.InnerHtml.IndexOf("destina")) != -1)
                    dest = elTR.FirstChild.InnerHtml.Substring(index + 9, elTR.FirstChild.InnerHtml.IndexOf(">") - 10 - index);

                if (!string.IsNullOrEmpty(dest))
                {
                    dest = dest.Replace("tsk", "note");
                    HtmlElement destEL = web.Document.GetElementById(dest);
                    if (destEL != null)
                    {
						if (destEL.Parent.Parent.Style.Equals("DISPLAY: block", StringComparison.CurrentCultureIgnoreCase))
						{
							if (!string.IsNullOrEmpty(destEL.InnerHtml))
							{
								if(!destEL.InnerHtml.Equals("<TEXTAREA style=\"WIDTH: 100%\" name=notes rows=5 wrap=hard></TEXTAREA><BUTTON align=\"right\">Save</BUTTON>"))
									if (MessageBox.Show(this.m_FormMain, "You have notes that have not been saved, are you sure you want to continue?", "Jonathan", 
										MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
										return;
							}
							destEL.InnerHtml = "";
							destEL.Parent.Parent.Style = "DISPLAY: none";
							return;
						}
                        destEL.Parent.Parent.Style = "DISPLAY: block";
                        destEL.Parent.Parent.FirstChild.Style = "BACKGROUND: #D8D8D8";
                        destEL.Parent.Parent.FirstChild.InnerHtml = "<span style=\"writing-mode: tb-rl;filter: flipv fliph;font-weight:bold;\">Notes</span>";
						destEL.InnerHtml = "<TEXTAREA name=\"notes\" rows=5 WRAP=HARD style=\"width:100%;\">" + destEL.InnerHtml + "</TEXTAREA><button align=\"right\">Save</button>";
                    }
                }
            }
        }

		/// <summary>
		/// Occurs when the Search Context menu item is clicked.
		/// </summary>
		/// <param name="sender">Search Context menu item.</param>
		/// <param name="e">Event Arguments.</param>
        void Search_Click (object sender, EventArgs e)
        {
            ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
            Webber web = this.GetWebber(tsmi);
            //HtmlElement elTD = web.MouseClickElement;
            string text = web.Selection;

            if (!string.IsNullOrEmpty(text))
			{
				// Get Cell (TD)...
				HtmlElement elTD = Common.GetTDElement(web);// this.GetTDElement(web);
				if (elTD == null) return;

                // Get the Version...
                int index = 0;
                string version = "";
                if ((index = elTD.OuterHtml.IndexOf("version")) != -1)
                {
                    version = elTD.OuterHtml.Substring(index + 9, elTD.OuterHtml.IndexOf(">") - 10 - index);
                    version = this.GetVersion(Convert.ToInt32(version));
                }

                // Search...
                this.m_FormMain.Search(version, text, this);
            }
        }

		/// <summary>
		/// Occurs when the Define Context menu item is clicked.
		/// </summary>
		/// <param name="sender">Define Context menu item.</param>
		/// <param name="e">Event Arguments.</param>
        void Define_Click (object sender, EventArgs e)
        {
            ToolStripMenuItem tsmi = sender as ToolStripMenuItem;
            Webber web = this.GetWebber(tsmi);
            string text = web.Selection;

            if (!string.IsNullOrEmpty(text))
            {
                // Search...
                this.m_FormMain.Search(text, this, Common.TYPE_REFERENCE);
            }
        }

		/// <summary>
		/// Occurs when the Context Menu is opening.
		/// </summary>
		/// <param name="sender">Context Menu Strip of Control.</param>
		/// <param name="e">Cancel Event Arguments.</param>
        void ctx_Opening (object sender, CancelEventArgs e)
        {
            System.Windows.Forms.ContextMenuStrip ctx = sender as ContextMenuStrip;
            if (ctx.Items.Count <= 0)
                return;

            Webber web = this.GetWebber((ToolStripMenuItem)ctx.Items[0]);
            ctx.Items["vcopy"].Enabled = false;
            ctx.Items["bookmark"].Enabled = false;
            ctx.Items["note"].Enabled = false;
            ctx.Items["vcopy"].Text = "Cannot Copy Verse";
            ctx.Items["bookmark"].Text = "Nothing to Book Mark";
			ctx.Items["note"].Text = "Cannot add a Note";

			if (string.IsNullOrEmpty(web.Selection))
			{
				ctx.Items["copy"].Enabled = false;
				ctx.Items["search"].Enabled = false;
				ctx.Items["define"].Enabled = false;
				ctx.Items["define"].Text = "Nothing to Lookup";
				ctx.Items["search"].Text = "Nothing to Search for";
			}
			else
			{
				ctx.Items["copy"].Enabled = true;
				ctx.Items["search"].Enabled = true;
				ctx.Items["define"].Enabled = true;
				ctx.Items["define"].Text = "Lookup Definitions for " + web.Selection.Split(' ')[0] + "...";
				ctx.Items["search"].Text = "Search for " + web.Selection.Split(' ')[0] + "...";
			}

			// Get Cell (TD)...
			HtmlElement elTD = Common.GetTDElement(web);
			if (elTD == null) return;

            // Get the Row (TR)...
			HtmlElement elTR = web.GetParentElement(elTD.Parent, "TR");
			if (elTR == null) return;

            // Lets Copy...
            int index = 0;
            if ((index = elTR.OuterHtml.IndexOf("passage")) != -1)
            {
                string passage = elTR.OuterHtml.Substring(index + 9, elTR.OuterHtml.IndexOf(">") - 10 - index);
                string[] parsedPassage = passage.Split('|');

                // Copy Verse...
                ctx.Items["vcopy"].Text = "Copy " + parsedPassage[0] + " " + parsedPassage[1] + ":" + parsedPassage[2];
                ctx.Items["vcopy"].Enabled = true;
                ctx.Items["vcopy"].Tag = parsedPassage[0] + " " + parsedPassage[1] + ":" + parsedPassage[2] + " - " + elTD.InnerText;

                // Book Mark...
                ctx.Items["bookmark"].Text = "Book Mark " + parsedPassage[0] + " " + parsedPassage[1] + ":" + parsedPassage[2];
                ctx.Items["bookmark"].Enabled = true;
                ctx.Items["note"].Text = "Add/Edit Notes for " + parsedPassage[0] + " " + parsedPassage[1] + ":" + parsedPassage[2];
                ctx.Items["note"].Enabled = true;

                if ((index = elTD.OuterHtml.IndexOf("version")) != -1)
                {
                    string version = elTD.OuterHtml.Substring(index + 9, elTD.OuterHtml.IndexOf(">") - 10 - index);
                    version = this.GetVersion(Convert.ToInt32(version));
                    ctx.Items["bookmark"].Tag = version + "|" + passage;
                    ctx.Items["bookmark"].Enabled = true;
                }
            }
        }

        #endregion

        #region -= Formatting =-

        /// <summary>
        /// Italisize the Selected Font...
        /// </summary>
        /// <param name="sender">ToolStripButton</param>
        /// <param name="e">EventArgs</param>
        void _btnItalic_Click (object sender, System.EventArgs e)
        {
            Webber web = this.GetWebber();
            if (web != null)
            {
                web.Document.ExecCommand("Italic", false, null);
                this.GetNewVerses("<EM>", web);
            }
        }

        /// <summary>
        /// Bold the Selected Font...
        /// </summary>
        /// <param name="sender">ToolStripButton</param>
        /// <param name="e">EventArgs</param>
        void _btnBold_Click (object sender, System.EventArgs e)
        {
            Webber web = this.GetWebber();
            if (web != null)
            {
                web.Document.ExecCommand("Bold", false, null);
                this.GetNewVerses("<STRONG>", web);
            }
        }

        /// <summary>
        /// Underline the Selected Font...
        /// </summary>
        /// <param name="sender">ToolStripButton</param>
        /// <param name="e">EventArgs</param>
        void _btnUnderline_Click (object sender, System.EventArgs e)
        {
            Webber web = this.GetWebber();
            if (web != null)
            {
                web.Document.ExecCommand("Underline", false, null);
                this.GetNewVerses("<U>", web);
            }
        }

        /// <summary>
        /// Change the Selected Text's Color...
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ForeColorPicker_SelectedColorChanged (object sender, EventArgs e)
        {
            Webber web = this.GetWebber();
            if (web != null)
            {
                Jonathan.ColorPicker.OfficeColorPicker colorPicker = ((Jonathan.ColorPicker.ToolStripColorDropDown)this._ForeColorPicker.DropDown).ColorPicker;
                if (colorPicker != null)
                {
                    web.Document.ExecCommand("ForeColor", false, ColorTranslator.ToHtml(colorPicker.Color));
                    this.GetNewVerses("<FONT", web);
                }
            }
        }

        /// <summary>
        /// Change the Selected Text's BackColor...
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void BackColorPicker_SelectedColorChanged (object sender, EventArgs e)
        {
            Webber web = this.GetWebber();
            if (web != null)
            {
                Jonathan.ColorPicker.OfficeColorPicker colorPicker = ((Jonathan.ColorPicker.ToolStripColorDropDown)this._BackColorPicker.DropDown).ColorPicker;
                if (colorPicker != null)
                {
                    web.Document.ExecCommand("BackColor", false, ColorTranslator.ToHtml(colorPicker.Color));
                    this.GetNewVerses("<FONT", web);
                }
            }
        }

        /// <summary>
        /// Gets the New Verses in the bibles..
        /// </summary>
        /// <param name="lookFor">Update to look for.</param>
        /// <param name="web">Webber with update</param>
        private void GetNewVerses (string lookFor, Webber web)
        {
            if (this.m_Type == Common.TYPE_REFERENCE)
            {
                this.GetNewReference(lookFor, web);
                return;
            }

            // Return if the Preface is seleted...
            if (this.m_List.SelectedNodes.Contains(this.m_List.Nodes[0]))
                return;

            web.ClearSelection();
            string txt = web.innerHTML;
            List<string[]> verses = new List<string[]>();
            if (!string.IsNullOrEmpty(txt))
            {
                txt = txt.Replace("\r\n", "");
                string[] tags = txt.Split(new string[] { "<TR", "<TD" }, StringSplitOptions.RemoveEmptyEntries);
                string[] verse = new string[3];
                foreach (string tag in tags)
                {
                    if (tag.Contains("passage=\""))
                    {
                        int index = tag.IndexOf("passage=");
                        verse[0] = tag.Substring(index + 9, tag.IndexOf(">") - 10 - index);
                    }
                    else if (tag.Contains("vAlign=top align=left version="))
                    {
                        // Version...
                        int index = tag.IndexOf("version=");
                        verse[2] = tag.Substring(index + 9, tag.IndexOf(">") - 10 - index);
                        verse[2] = this.m_Versions[Convert.ToInt32(verse[2])].Path;

                        // Text...
                        int start = tag.IndexOf('>') + 1;
                        int end = tag.LastIndexOf('<');
                        verse[1] = tag.Substring(start, end - start);

                        // Passage
                        if (string.IsNullOrEmpty(verse[0]))
                        {
                            verse[0] = verses[verses.Count - 1][0];
                        }

                        verses.Add(verse);
                        verse = new string[3];
                        // Copy the last passage...
                    }
                }
            }

            // Remove the verses that did not change...
            // If we undo the look for (i.e. change from bold to not bold), then we will remove all verses... Hmmmm....
            /*for (int a = verses.Count - 1; a >= 0; a--)
            {
                if (!verses[a][1].Contains(lookFor))
                {
                    verses.Remove(verses[a]);
                }
            }*/

            // Sort and return...
            verses.Sort(new NewVerseListComparer());

            Thread t = new Thread(new ParameterizedThreadStart(this.UpdateBibleTexts));
            t.Start(verses);
        }

        /// <summary>
        /// Gets the New Reference Text..
        /// </summary>
        /// <param name="lookFor">Update to look for.</param>
        /// <param name="web">Webber with update</param>
        private void GetNewReference (string lookFor, Webber web)
        {
            if (this.m_RefList.SelectedItems.Count > 0)
            {
                // Do not Do Preface...
                if (this.m_RefList.SelectedItems[0] == this.m_RefList.Items[0])
                    return;

                string refTxt = web.innerHTML;
                if (!string.IsNullOrEmpty(refTxt))
                {
                    List<string[]> refList = new List<string[]>();
                    string[] lines = refTxt.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                    bool nextTD = false;
                    string[] refItem = new string[3];
                    refItem[2] = this.m_Versions[0].Path;
                    foreach (string line in lines)
                    {
                        if (line.StartsWith("<H3>"))
                        {
                            refItem[0] = line.Substring(4, line.LastIndexOf("</H3></TD></TR>") - 4);
                            nextTD = true;
                        }
                        else if (line.StartsWith("<TD>") && nextTD)
                        {
                            refItem[1] = line.Substring(4, line.LastIndexOf("</TD></TR>") - 4);
                            refList.Add(refItem);
                            refItem = new string[3];
                            nextTD = false;
                        }
                    }

                    if (refList.Count > 0)
                    {
                        Thread t = new Thread(new ParameterizedThreadStart(this.UpdateReferenceTexts));
                        t.Start(refList);
                    }
                }
            }

        }

        /// <summary>
        /// Updates the Reference's text in the data base.
        /// </summary>
        /// <param name="verseList">List of Items</param>
        private void UpdateReferenceTexts (object refItems)
        {
            List<string[]> refList = (List<string[]>)refItems;

            if (refList.Count > 0)
            {
                bool dbHasChanges = false;
                Database db = new Database(refList[0][2]);
                Query qBookList = new Query(QueryType.SELECT, Common.TABLE_BOOK_LIST);
                qBookList.SELECT("*");
                db.RunQuery(qBookList);
                foreach (string[] refItem in refList)
                {
                    Query qSel = new Query(QueryType.SELECT);
                    if (qBookList.RowsReturned == 1)
                        qSel.Table = qBookList.Results.GetFieldString(0, 0);
                    else
                        qSel.Table = refItem[0][0].ToString();
                    qSel.SELECT("Text");
                    qSel.WHERE("Word", Operator.EQUALS, refItem[0]);
                    db.RunQuery(qSel);

                    if (qSel.RowsReturned > 0)
                    {
                        if (!qSel.Results.GetFieldString(0, 0).Equals(refItem[0]))
                        {
                            Query qUpdate = new Query(QueryType.UPDATE, qSel.Table);
                            qUpdate.SET("Text", refItem[1]);
                            qUpdate.WHERE("Word", Operator.EQUALS, refItem[0]);
                            db.RunQuery(qUpdate);
                            dbHasChanges = true;
                        }
                    }
                }

                if(dbHasChanges)
                    db.Commit();
            }
        }

        /// <summary>
        /// Updates the Bible's text in the data base.
        /// </summary>
        /// <param name="verseList">List of Verses</param>
        private void UpdateBibleTexts (object verseList)
        {
            List<string[]> verses = (List<string[]>)verseList;

            Database db = null;
            string oldPath = "";
            bool dbHasChanges = false;
            foreach (string[] verse in verses)
            {
                if (oldPath != verse[2])
                {
                    if (db != null && dbHasChanges)
                    {
                        db.Commit();
                        dbHasChanges = false;
                    }

                    db = new Database(verse[2]);
                    oldPath = verse[2];
                }
                string[] parsedVerse = verse[0].Split('|');
                Query q = new Query(QueryType.SELECT, parsedVerse[0]);
                q.SELECT("Text");
                q.WHERE("Chapter", Operator.EQUALS, parsedVerse[1]);
                q.WHERE("Verse", Operator.EQUALS, parsedVerse[2]);
                db.RunQuery(q);
                if (q.RowsReturned > 0)
                {
                    if (!q.Results.GetFieldString(0, 0).Equals(verse[1]))
                    {
                        Query qUpdate = new Query(QueryType.UPDATE, parsedVerse[0]);
                        qUpdate.SET("Text", verse[1]);
                        qUpdate.WHERE("Chapter", Operator.EQUALS, parsedVerse[1]);
                        qUpdate.WHERE("Verse", Operator.EQUALS, parsedVerse[2]);
                        db.RunQuery(qUpdate);
                        dbHasChanges = true;
                    }
                }
            }
            if (db != null && dbHasChanges)
                db.Commit();
        }

        #endregion
    }
}
